///////////////////////////////////////////////////////////////////////////////
//
// DBT86 Project : x86 Platform : x86 Interpreter : flags.h
// Copyright (C) 2004 by Ben Hertzberg and Stanford University
// All Rights Reserved
//
// This code may not be used for any purpose without the express written
// consent of the author.  See the LICENSE.txt file for details.
//
//
// DESCRIPTION
//
// This header is used to implement lazy flag evaluation for x86.
//
///////////////////////////////////////////////////////////////////////////////


#ifndef __FLAGS_H__
#define __FLAGS_H__

#include "x86.h"

//
// Global definitions
//

// these variants are used by instructions that assume lazy responsibility for all flags
#define SET_FLAGS(code,src1,src2) { X86_CTXT(flagsOp) = code; X86_CTXT(flagsSrc1) = src1; X86_CTXT(flagsSrc2) = src2; }
#define SET_FLAGS_X(code,src1,src2,src3) {X86_CTXT(flagsOp) = code; X86_CTXT(flagsSrc1) = src1; X86_CTXT(flagsSrc2) = src2; X86_CTXT(flagsSrc3) = src3; }
#define SET_FLAGS_U(code,src1) { X86_CTXT(flagsOp) = code; X86_CTXT(flagsSrc1) = src1; }

// this variant is used by rotates (not very efficient)
#define SET_FLAGS_CF_OF(cf,of) { \
    forceEvaluateFlags(EFLAGS_BIT_A | EFLAGS_BIT_P | EFLAGS_BIT_S | EFLAGS_BIT_Z); \
    X86_CTXT(flagsSrc1) |= (cf) ? EFLAGS_BIT_C : 0; \
    X86_CTXT(flagsSrc1) |= (of) ? EFLAGS_BIT_O : 0; \
  }

#define SET_FLAGS_ZF(zf) { \
    forceEvaluateFlags(EFLAGS_BIT_A | EFLAGS_BIT_P | EFLAGS_BIT_S | EFLAGS_BIT_C | EFLAGS_BIT_O); \
    X86_CTXT(flagsSrc1) |= (zf) ? EFLAGS_BIT_Z : 0; \
  }

// this variant is used by BSF/BSR (efficient) because we know exactly what to set
// by the time we have the result (even less work than saving operation sources)
#define SET_FLAGS_EAGER(x) { X86_CTXT(flagsOp) = CF_NOT_LAZY; X86_CTXT(flagsSrc1) = (x); }

#define GET_CARRY_FLAG getCarryFlag()
#define GET_CARRY_FLAG_AS_BOOL (getCarryFlag() != 0)
#define GET_AUX_FLAG getAuxFlag()
#define GET_ZERO_FLAG getZeroFlag()
#define GET_DIRECTION_FLAG getDirectionFlag()

#define COND_EVAL_O getOverflowFlag()
#define COND_EVAL_P getParityFlag()
#define COND_EVAL_S (getSignFlag() != 0)
#define COND_EVAL_E getZeroFlag()

#define COND_EVAL_B (getCarryFlag() != 0)
#define COND_EVAL_BE cond_eval_be()
#define COND_EVAL_L cond_eval_l()
#define COND_EVAL_LE cond_eval_le()

#define CF_OP_SPEC(x) ((x) << 2)
#define CF_SZ_SPEC(x) (x)
#define CF_SZ_MASK    0x03

#define CF_INVALID     -1
#define CF_NOT_LAZY    0x00
#define CF_ADD_BYTE    (CF_OP_SPEC(0x01) | CF_SZ_SPEC(0x01))
#define CF_ADD_WORD    (CF_OP_SPEC(0x01) | CF_SZ_SPEC(0x02))
#define CF_ADD_DWORD   (CF_OP_SPEC(0x01) | CF_SZ_SPEC(0x03))
#define CF_OR_BYTE     (CF_OP_SPEC(0x02) | CF_SZ_SPEC(0x01))
#define CF_OR_WORD     (CF_OP_SPEC(0x02) | CF_SZ_SPEC(0x02))
#define CF_OR_DWORD    (CF_OP_SPEC(0x02) | CF_SZ_SPEC(0x03))
#define CF_ADC_BYTE    (CF_OP_SPEC(0x03) | CF_SZ_SPEC(0x01))
#define CF_ADC_WORD    (CF_OP_SPEC(0x03) | CF_SZ_SPEC(0x02))
#define CF_ADC_DWORD   (CF_OP_SPEC(0x03) | CF_SZ_SPEC(0x03))
#define CF_SBB_BYTE    (CF_OP_SPEC(0x04) | CF_SZ_SPEC(0x01))
#define CF_SBB_WORD    (CF_OP_SPEC(0x04) | CF_SZ_SPEC(0x02))
#define CF_SBB_DWORD   (CF_OP_SPEC(0x04) | CF_SZ_SPEC(0x03))
#define CF_AND_BYTE    (CF_OP_SPEC(0x05) | CF_SZ_SPEC(0x01))
#define CF_AND_WORD    (CF_OP_SPEC(0x05) | CF_SZ_SPEC(0x02))
#define CF_AND_DWORD   (CF_OP_SPEC(0x05) | CF_SZ_SPEC(0x03))
#define CF_SUB_BYTE    (CF_OP_SPEC(0x06) | CF_SZ_SPEC(0x01))
#define CF_SUB_WORD    (CF_OP_SPEC(0x06) | CF_SZ_SPEC(0x02))
#define CF_SUB_DWORD   (CF_OP_SPEC(0x06) | CF_SZ_SPEC(0x03))
#define CF_XOR_BYTE    (CF_OP_SPEC(0x07) | CF_SZ_SPEC(0x01))
#define CF_XOR_WORD    (CF_OP_SPEC(0x07) | CF_SZ_SPEC(0x02))
#define CF_XOR_DWORD   (CF_OP_SPEC(0x07) | CF_SZ_SPEC(0x03))
#define CF_INC_BYTE    (CF_OP_SPEC(0x08) | CF_SZ_SPEC(0x01))
#define CF_INC_WORD    (CF_OP_SPEC(0x08) | CF_SZ_SPEC(0x02))
#define CF_INC_DWORD   (CF_OP_SPEC(0x08) | CF_SZ_SPEC(0x03))
#define CF_DEC_BYTE    (CF_OP_SPEC(0x09) | CF_SZ_SPEC(0x01))
#define CF_DEC_WORD    (CF_OP_SPEC(0x09) | CF_SZ_SPEC(0x02))
#define CF_DEC_DWORD   (CF_OP_SPEC(0x09) | CF_SZ_SPEC(0x03))
#define CF_NEG_BYTE    (CF_OP_SPEC(0x0A) | CF_SZ_SPEC(0x01))
#define CF_NEG_WORD    (CF_OP_SPEC(0x0A) | CF_SZ_SPEC(0x02))
#define CF_NEG_DWORD   (CF_OP_SPEC(0x0A) | CF_SZ_SPEC(0x03))
#define CF_SHL_BYTE    (CF_OP_SPEC(0x0B) | CF_SZ_SPEC(0x01))
#define CF_SHL_WORD    (CF_OP_SPEC(0x0B) | CF_SZ_SPEC(0x02))
#define CF_SHL_DWORD   (CF_OP_SPEC(0x0B) | CF_SZ_SPEC(0x03))
#define CF_SHR_BYTE    (CF_OP_SPEC(0x0C) | CF_SZ_SPEC(0x01))
#define CF_SHR_WORD    (CF_OP_SPEC(0x0C) | CF_SZ_SPEC(0x02))
#define CF_SHR_DWORD   (CF_OP_SPEC(0x0C) | CF_SZ_SPEC(0x03))
#define CF_SAR_BYTE    (CF_OP_SPEC(0x0D) | CF_SZ_SPEC(0x01))
#define CF_SAR_WORD    (CF_OP_SPEC(0x0D) | CF_SZ_SPEC(0x02))
#define CF_SAR_DWORD   (CF_OP_SPEC(0x0D) | CF_SZ_SPEC(0x03))
#define CF_BCD         (CF_OP_SPEC(0x0E) | CF_SZ_SPEC(0x01))

IVAL getCarryFlag();
IVAL getOverflowFlag();
IVAL getAuxFlag();
IVAL getParityFlag();
IVAL getSignFlag();
IVAL getZeroFlag();
IVAL getDirectionFlag();
IVAL cond_eval_be();
IVAL cond_eval_l();
IVAL cond_eval_le();
IVAL getFlags();
void setFlags(IVAL f);
void forceEvaluateFlags(INT bits);


#ifdef INCL_FLAGS_LOCAL
//
// Local definitions
//

#endif
#endif
